home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / t3_1 / nexttsrc.lha / nexttsources / sources / comp / back_end / bookkeep.t < prev    next >
Encoding:
Text File  |  1990-06-19  |  17.0 KB  |  509 lines

  1. (herald (back_end bookkeep)
  2.   (env t (orbit_top defs)))
  3.  
  4. ;;; Copyright (c) 1985 Yale University
  5. ;;;     Authors: N Adams, R Kelsey, D Kranz, J Philbin, J Rees.
  6. ;;; This material was developed by the T Project at the Yale University Computer 
  7. ;;; Science Department.  Permission to copy this software, to redistribute it, 
  8. ;;; and to use it for any purpose is granted, subject to the following restric-
  9. ;;; tions and understandings.
  10. ;;; 1. Any copy made of this software must include this copyright notice in full.
  11. ;;; 2. Users of this software agree to make their best efforts (a) to return
  12. ;;;    to the T Project at Yale any improvements or extensions that they make,
  13. ;;;    so that these may be included in future releases; and (b) to inform
  14. ;;;    the T Project of noteworthy uses of this software.
  15. ;;; 3. All materials developed as a consequence of the use of this software
  16. ;;;    shall duly acknowledge such use, in accordance with the usual standards
  17. ;;;    of acknowledging credit in academic research.
  18. ;;; 4. Yale has made no warrantee or representation that the operation of
  19. ;;;    this software will be error-free, and Yale is under no obligation to
  20. ;;;    provide any services, by way of maintenance, update, or otherwise.
  21. ;;; 5. In conjunction with products arising from the use of this material,
  22. ;;;    there shall be no use of the name of the Yale University nor of any
  23. ;;;    adaptation thereof in any advertising, promotional, or sales literature
  24. ;;;    without prior written consent from Yale in each case.
  25. ;;;
  26.  
  27. ;;; Copyright (c) 1985 David Kranz
  28.  
  29. (define (addressable? value)
  30.   (or (fixnum? value)
  31.       (char? value)
  32.       (eq? value '#F)
  33.       (eq? value '#T)))
  34.  
  35. (define-integrable (reg-offset x y) (cons x y))
  36.  
  37. (define-integrable (machine-num x) ($ x))
  38.  
  39.  
  40. (define (lit x)
  41.   (xcond ((fixnum? x)
  42.           ($ (* x 4)))
  43.          ((char? x)
  44.           ($ (fx+ (fixnum-ashl (char->ascii x) 8) header/char)))))
  45.  
  46.  
  47. (define-integrable (register? x)
  48.   (and (fixnum? x) (fx>= x 0) (fx< x *real-registers*)))
  49.  
  50.  
  51. ;;; Registers and temps are represented in the same structure
  52.  
  53. (define-integrable reg-node
  54.   (object (lambda (reg) 
  55.             (vref *registers* reg))
  56.           ((setter self) 
  57.            (lambda (reg node)
  58.              (vset *registers* reg node)))))
  59.                          
  60. (define-integrable temp-node reg-node)
  61.  
  62.  
  63. (define (reg-type reg)
  64.     (if (or (fx< reg *scratch-registers*)
  65.             (fx>= reg (fx+ *real-registers* *pointer-temps*)))
  66.         'scratch 
  67.         'pointer))
  68.  
  69.  
  70.  
  71. ;;; ->REGISTER Move the value of leaf-node REF into a register of type TYPE
  72. ;;; which can be either '* or a specific register. Force an existing value out
  73. ;;; if necessary,
  74.  
  75. (define (->register type node var where)
  76.   (let ((accessor (access-value node var)))
  77.     (cond ((and (register? accessor)
  78.                 (or (and (eq? (reg-type accessor) type)
  79.                          (eq? where '*))
  80.                     (eq? accessor where)))
  81.            accessor)
  82.           (else 
  83.            (cond ((register? accessor)
  84.                   (set (register-loc var) nil)
  85.                   (cond ((locked? accessor)
  86.                          (set (cdr (reg-node accessor)) nil))
  87.                         (else
  88.                          (set (reg-node accessor) nil)))))
  89.            (into-register type node var accessor where)))))
  90.           
  91. (define (in-register? type value where)
  92.   (let ((reg (register-loc value)))
  93.     (and reg
  94.          (eq? (reg-type reg) type)
  95.          (or (eq? where '*)
  96.              (eq? where reg)))))
  97.  
  98.  
  99. (define (get-target-register node t-spec)
  100.   (cond ((register? t-spec)
  101.          (cond ((or (maybe-free t-spec ((call-arg 1) node))
  102.                     (if (locked? t-spec)
  103.                         (dying? (cdr (reg-node t-spec)) node)
  104.                          (dying? (reg-node t-spec) node)))
  105.                 t-spec)
  106.                (else
  107.                 (get-register (reg-type t-spec) node '*))))
  108.         (else
  109.          (get-register t-spec node '*))))
  110.  
  111. (lset get-register (lambda (type node where)
  112.   (cond ((neq? where '*)
  113.          (free-register node where)
  114.          where)
  115.         ((neq? type 'scratch)
  116.          (really-get-register 'pointer node *scratch-registers* *real-registers* t))
  117.         (else
  118.          (really-get-register 'scratch node
  119.                               0
  120.                               *scratch-registers* t)))))
  121.  
  122. ;(lset get-register (lambda (type node where)
  123. ;  (cond ((neq? where '*)
  124. ;         (free-register node where)
  125. ;         where)
  126. ;        ((neq? type 'scratch)
  127. ;         (iterate loop ((i AN))
  128. ;           (cond ((fx< i P)
  129. ;                  (if kick? (select-and-kick-register node 'pointer) nil))
  130. ;                 ((not (reg-node i))
  131. ;                  i)
  132. ;                 (else
  133. ;                  (loop (fx- i 1))))))
  134. ;        (else
  135. ;         (really-get-register 'scratch node
  136. ;                              0
  137. ;                              *scratch-registers* t)))))
  138.  
  139. (define (get-reg-if-free spec node)
  140.   (xcond ((register? spec)
  141.           (if (reg-node spec) nil spec))
  142.          ((eq? spec 'pointer)
  143.           (really-get-register spec node *scratch-registers* *real-registers* nil))
  144.          ((eq? spec 'scratch)
  145.           (really-get-register spec node 0 *scratch-registers* nil))
  146.          ((eq? spec '*)
  147.           (really-get-register spec node 0 *real-registers* nil))))
  148.  
  149. (define (really-get-register type node start stop kick?)
  150.   (iterate loop ((i start))
  151.     (cond ((fx>= i stop)
  152.            (if kick? (select-and-kick-register node type) nil))
  153.           ((not (reg-node i))
  154.            i)
  155.           (else
  156.            (loop (fx+ i 1))))))
  157.  
  158. (define (into-register type node value access where)
  159.   (cond ((in-register? type value where)
  160.          (register-loc value))
  161.         (else         
  162.          (let ((reg (get-register type node where)))
  163.            (generate-move access reg)
  164.            (cond ((register-loc value)
  165.                   => (lambda (reg)
  166.                        (set (reg-node reg) nil))))
  167.            (mark value reg)
  168.            reg))))
  169.  
  170.  
  171. ;;; SELECT-AND-KICK-REGISTER The first register which is not locked or used soo
  172. ;;; is selected.  If none satisfy then the first register  is selected.
  173.                                           
  174. (define (select-and-kick-register node type)
  175.   (cond ((eq? type 'pointer) 
  176.          (iterate loop ((i (fx+ *scratch-registers* 1)) (default P)) ;kick P?
  177.            (cond ((fx>= i *real-registers*)
  178.                   (kick-register node default)
  179.                   default)
  180.                  ((locked? i) 
  181.                   (loop (fx+ i 1) default))
  182.                  ((not (used-soon? node (reg-node i)))
  183.                   (kick-register node i) 
  184.                   i)
  185.                  (else (loop (fx+ i 1) i)))))
  186.         (else
  187.          (iterate loop ((i 0) (default nil))
  188.            (cond ((fx>= i *scratch-registers*)
  189.                   (free-register node default)
  190.                   default)
  191.                  ((locked? i) 
  192.                   (loop (fx+ i 1) default))
  193.                  ((not (used-soon? node (reg-node i))) 
  194.                   (free-register node i)
  195.                   i)
  196.                  (else (loop (fx+ i 1) i)))))))
  197.                                          
  198.  
  199. ;;; USED-SOON? Is this variable used at this node or at one of its
  200. ;;; continuations?
  201.  
  202. (define (used-soon? node value)                                        
  203.   (let ((var-used? (lambda (arg)
  204.                       (and (leaf-node? arg)
  205.                            (eq? (leaf-value arg) value)))))
  206.      (or (any? var-used? (call-args node))
  207.          (any? (lambda (cont)
  208.                  (any? var-used? (call-args (lambda-body cont))))
  209.                (continuations node)))))
  210.  
  211. (define-integrable (free-register node reg)
  212.   (if (reg-node reg) (kick-register node reg)))
  213.  
  214. (define (maybe-free reg cont)
  215.   (cond ((reg-node reg)
  216.          => (lambda (var)
  217.               (cond ((and (variable? var)
  218.                           (lambda-node? cont)
  219.                           (let ((spec (likely-next-reg var cont)))
  220.                             (cond ((and (fixnum? spec)
  221.                                         (not (reg-node spec)))
  222.                                    (generate-move reg spec)   
  223.                                    (set (reg-node reg) nil)
  224.                                    (set (register-loc var) nil)
  225.                                    (mark var spec)
  226.                                    t)
  227.                                   (else nil)))))
  228.                      (else nil))))
  229.          (else t)))
  230.  
  231.  
  232.  
  233. (define (kick-register node reg) 
  234.   (let ((value (reg-node reg)))
  235.     (cond ((locked? reg)
  236.            (error "attempt to kick out of locked register"))
  237.           ((or (temp-loc value)
  238.                (not (variable? value)))
  239.            (set (register-loc value) nil)
  240.            (set (reg-node reg) nil))
  241.           (else
  242.            (let ((temp (get-temp value (reg-type reg) node)))
  243.              (set (register-loc value) nil)
  244.              (set (temp-loc value) temp)
  245.              (set (reg-node reg) nil)
  246.              (really-rep-convert node 
  247.                                  reg 
  248.                                  (variable-rep value) 
  249.                                  temp 
  250.                                  (variable-rep value)))))))
  251.  
  252.  
  253.  
  254. (define (really-get-temp type node)
  255.   (cond ((eq? type 'scratch)
  256.          (really-get-register 'scratch node
  257.                               (fx+ *real-registers* *pointer-temps*)
  258.                               *no-of-registers*
  259.                               nil))
  260.         (else
  261.          (really-get-register 'pointer node
  262.                               *real-registers*
  263.                               (fx+ *real-registers* *pointer-temps*)
  264.                               nil))))
  265.  
  266. (define (get-temp value type node)
  267.   (cond ((really-get-temp type node)
  268.          => (lambda (temp)
  269.               (if (fx> temp *max-temp*)
  270.                   (set *max-temp* temp))
  271.               (set (temp-node temp) value)
  272.               temp))
  273.         (else
  274.          (bug "all temps used"))))
  275.  
  276. (define-integrable (cont node)
  277.   (car (call-args node)))
  278.              
  279. (define (continuations node)               
  280.   (iterate loop ((i (call-exits node)) (args '()))
  281.     (cond ((fx= i 0) args)
  282.           (else
  283.            (let ((arg ((call-arg i) node)))
  284.              (loop (fx- i 1)
  285.                    (cond ((lambda-node? arg) (cons arg args))
  286.                          ((variable-known (leaf-value arg))
  287.                           => (lambda (label) (cons label args)))
  288.                          (else args))))))))
  289.  
  290. (define-integrable (then-cont node)
  291.   (car (call-args node)))
  292.  
  293. (define-integrable (else-cont node)
  294.   (cadr (call-args node)))
  295.  
  296. (define-integrable (kill-if-dying var node)
  297.   (if (dying? var node) (kill var)))
  298.  
  299. (define (kill-if-dead node where)
  300.   (cond ((lambda-node? node)
  301.          (walk (lambda (var)
  302.                  (if (not (or (memq? var (lambda-live where))
  303.                               (fx= (variable-number var) 0)))
  304.                      (kill var)))
  305.                (lambda-live node)))
  306.         (else
  307.      (let ((var (leaf-value node)))
  308.        (cond ((not (variable? var))
  309.           (kill var))
  310.          (else
  311.           (let ((var (cond ((variable-known var) => lambda-self-var)
  312.                    (else var))))
  313.             (if (not (memq? var (lambda-live where)))
  314.             (kill var)))))))))
  315.  
  316. (define (kill value)
  317.     (cond ((register-loc value)
  318.            => (lambda (reg)
  319.                 (cond ((locked? reg)
  320.                        (if (neq? (cdr (reg-node reg)) value)
  321.                            (bug "horrible inconsistancy reg ~S value ~S"
  322.                                  reg
  323.                                  value))
  324.                        (set (cdr (reg-node reg)) nil))
  325.                       (else
  326.                        (if (neq? (reg-node reg) value)
  327.                            (bug "horrible inconsistancy reg ~S value ~S"
  328.                                  reg
  329.                                  value))
  330.                        (set (reg-node reg) nil)))
  331.                  (set (register-loc value) nil))))
  332.     (cond ((temp-loc value)
  333.            => (lambda (reg)
  334.                 (cond ((locked? reg)
  335.                        (if (neq? (cdr (temp-node reg)) value)
  336.                            (bug "horrible inconsistancy reg ~S value ~S"
  337.                                  reg
  338.                                  value))
  339.                        (set (cdr (temp-node reg)) nil))
  340.                       (else
  341.                        (if (neq? (temp-node reg) value)
  342.                            (bug "horrible inconsistancy reg ~S value ~S"
  343.                                  reg
  344.                                  value))
  345.                        (set (temp-node reg) nil)))
  346.                  (set (temp-loc value) nil)))))
  347.  
  348. (define (live? value node)                    
  349.   (let ((value (cond ((and (pair? value) (variable? (cdr value)))
  350.                       (cdr value))
  351.                      ((variable? value) value)
  352.                      (else nil))))
  353.      (cond ((not value) nil)
  354.        ((eq? value (lambda-self-var *lambda*)) t)
  355.            (else 
  356.             (any? (lambda (cont)
  357.                      (memq? value (lambda-live cont)))
  358.                   (continuations node))))))
  359.  
  360. (define-integrable (dying? value node)
  361.   (not (live? value node)))
  362.  
  363. (define (dead? value node)
  364.   (let ((parent (node-parent node)))
  365.     (not (and (variable? value)
  366.               (or (memq? value (lambda-variables parent))
  367.                   (memq? value (lambda-live parent)))))))
  368.  
  369. ;;; pools for vector of registers (see ALLOCATE-CONDITIONAL-PRIMOP in reg.t)
  370.  
  371. (define register-vector-pool 
  372.         (make-pool 'reg-vec-pool 
  373.                    (lambda () (make-vector *no-of-registers*))
  374.                    15
  375.                    vector?))
  376.  
  377. (define-integrable (copy-registers)
  378.   (vector-replace (obtain-from-pool register-vector-pool)
  379.                   *registers*
  380.                   *no-of-registers*))
  381.                            
  382. (define-integrable (return-registers)
  383.   (return-to-pool register-vector-pool *registers*))
  384.  
  385. (define (restore-slots)
  386.     (restore-registers)
  387.     (restore-temps))
  388.  
  389. (define (restore-registers)
  390.   (do ((i 0 (fx+ i 1)))
  391.       ((fx>= i *real-registers* ))
  392.     (cond ((reg-node i)
  393.            (set (register-loc (reg-node i)) i)))))
  394.  
  395. (define (restore-temps)
  396.   (do ((i *real-registers* (fx+ i 1)))
  397.       ((fx>= i *no-of-registers* ))
  398.     (cond ((temp-node i)
  399.            (set (temp-loc (temp-node i)) i)))))
  400.  
  401.  
  402.  
  403. (define (clear-slots)
  404.   (vector-fill *registers* nil)
  405.   (recycle *locations*)
  406.   (set *locations* (make-table 'locations)))
  407.          
  408. (define *lock-mark* (object nil ((identification self) 'lock)))
  409.  
  410.  
  411. (define-integrable (lock reg)
  412.   (if (fx< reg *no-of-registers*)
  413.       (set (reg-node reg)
  414.            (cons *lock-mark* (reg-node reg)))))
  415.  
  416. (define-integrable (unlock reg)
  417.   (if (fx< reg *no-of-registers*)
  418.       (set (reg-node reg)
  419.            (cdr (reg-node reg)))))
  420.  
  421. (define-integrable (locked? reg)
  422.   (let ((n (reg-node reg)))
  423.     (and (pair? n) (eq? (car n) *lock-mark*))))
  424.  
  425. (define (protect-access access)
  426.   (cond ((fixnum? access)
  427.          (cond ((fx>= access 0)
  428.                 (lock access))))
  429.         ((fg? access))
  430.         ((register? (car access)) 
  431.          (if (fxn= (car access) SP)
  432.              (lock (car access))))
  433.         ((pair? (car access))
  434.          (lock (caar access))
  435.          (lock (cdar access)))))
  436.          
  437. (define (release-access access)
  438.   (cond ((fixnum? access)
  439.          (cond ((fx>= access 0)
  440.                 (unlock access))))
  441.         ((fg? access))
  442.         ((register? (car access)) 
  443.          (if (fxn= (car access) SP)
  444.              (unlock (car access))))
  445.         ((pair? (car access))
  446.          (unlock (caar access))
  447.          (unlock (cdar access)))))
  448.               
  449. (define (mark value reg)
  450.   (set (reg-node reg) value)
  451.   (if (register? reg)
  452.       (set (register-loc value) reg)
  453.       (set (temp-loc value) reg)))
  454.          
  455.  
  456. (define (mark-temp value reg)
  457.   (set (temp-node reg) value)
  458.   (set (temp-loc value) reg))
  459.  
  460.  
  461.  
  462. ;;; Locations
  463. ;;;==========================================================================
  464. ;;;   Keeps track of where values are.
  465. ;;; A table of a-lists of form ((<type-of-location> . <index>)...) indexed by
  466. ;;; leaf values, i.e. variables, primops, or literals.
  467.  
  468. (lset *locations* (make-table 'locations))
  469.  
  470. (define-integrable (leaf-locations value)
  471.    (table-entry *locations* value))
  472.  
  473. (define-integrable register-loc
  474.   (object (lambda (value)
  475.             (get-location value 'reg))
  476.     ((identification self) 'register-loc)
  477.     ((setter self)
  478.      (lambda (value reg)
  479.        (if (null? reg)
  480.            (clear-location value 'reg)
  481.            (set-location value 'reg reg))))))
  482.  
  483. (define-integrable temp-loc
  484.   (object (lambda (value)
  485.             (get-location value 'temp))
  486.     ((identification self) 'temp-loc)
  487.     ((setter self)
  488.      (lambda (value temp)
  489.        (if (null? temp)
  490.            (clear-location value 'temp)
  491.            (set-location value 'temp temp))))))
  492.  
  493. (define-integrable (get-location value type)
  494.   (cdr (assq type (leaf-locations value))))
  495.  
  496. (define (set-location value type number)
  497.   (let ((locs (leaf-locations value)))
  498.     (cond ((assq type locs)
  499.            => (lambda (pair)
  500.                 (set (cdr pair) number)))
  501.           (else
  502.            (set-table-entry *locations* value (cons (cons type number) locs))))))
  503.  
  504. (define (clear-location value type)
  505.   (let ((locs (leaf-locations value)))
  506.     (set-table-entry *locations* value
  507.          (del! (lambda (x y) (eq? x (car y))) type locs))
  508.     nil))
  509.